#!/bin/sh
# Usage:
# runtest [applet1] [applet2...]

# A temp directory to dump the rustybox binary into.
bindir="$(mktemp -d)"

# Build the rustybox binary. --out-dir is technically an unstable option. For
# some reason using target/debug/rustybox doesn't work as of cargo
# 1.41.0-nightly (626f0f40e 2019-12-03).
cargo build --all-features -Z unstable-options --out-dir "$bindir"

# The testsuite dir.
lcwd=$(pwd)
[ x"$tsdir" != x"" ] || tsdir="$lcwd"

# Why is this necessary?
PATH="$bindir:$PATH"

# Which tests require .config and what is it?
export bindir   # some tests need to look at $bindir/.config

if [ x"$VERBOSE" = x ]; then
    export VERBOSE=
fi

if [ x"$1" = x"-v" ]; then
    export VERBOSE=1
    shift
fi

implemented=$(
    printf "rustybox " # always implemented
    "$bindir/rustybox" 2>&1 |
    while read line; do
        if [ x"$line" = x"Functions:" ]; then
            xargs | sed 's/,//g'
            break
        fi
    done
    )

# If no applet names are given we test all of them.
applets="$implemented"
# If a list of applet names have been given, we only test those.
if [ $# -ne 0 ]; then
    applets="$@"
fi

# Populate a directory with links to all rustybox applets
LINKSDIR="$(mktemp -d)"
"$bindir/rustybox" --install -s "$LINKSDIR"

. ./testing.sh

total_failed=0

# Run one old-style test.
# Tests are stored in applet/testcase shell scripts.
# They are run using "sh -x -e applet/testcase".
# Option -e will make testcase stop on the first failed command.
run_applet_testcase()
{
    applet="$1"
    testcase="$2"

    status=0
    uc_applet=$(echo "$applet" | tr a-z A-Z)
    testname="$testcase"

    testname="${testname##*/}" # take basename
    # if grep "^# CONFIG_$uc_applet is not set$" "$bindir/.config" >/dev/null; then
    # 	echo "UNTESTED: $testname"
    # 	return 0
    # fi

    # if grep "^# FEATURE: " "$testcase" >/dev/null; then
    # 	local feature=$(sed -ne 's/^# FEATURE: //p' "$testcase")

    # 	for f in $feature; do
    # 		if grep "^# $f is not set$" "$bindir/.config" >/dev/null; then
    # 			echo "UNTESTED: $testname"
    # 			return 0
    # 		fi
    # 	done
    # fi

    rm -rf ".tmpdir.$applet"
    mkdir -p ".tmpdir.$applet"
    cd ".tmpdir.$applet" || return 1

#	echo "Running testcase $testcase"
    d="$tsdir" \
        sh -x -e "$testcase" >"$testname.stdout.txt" 2>&1 || status=$?
    if [ $status -ne 0 ]; then
        echo "FAIL: $testname"
        if [ x"$VERBOSE" != x ]; then
            cat "$testname.stdout.txt"
        fi
    else
        echo "PASS: $testname"
    fi

    cd ..
    rm -rf ".tmpdir.$applet"

    return $status
}

# Run all old-style tests for given applet
run_oldstyle_applet_tests()
{
    local applet="$1"
    local status=0

    for testcase in "$tsdir/$applet"/*; do
        # switch on basename of $testcase
        case "${testcase##*/}" in
            .*)     continue ;;    # .svn, .git etc
            *~)     continue ;;    # backup files
            "CVS")  continue ;;
            \#*)    continue ;;    # CVS merge residues
            *.mine) continue ;;    # svn-produced junk
            *.r[0-9]*) continue ;; # svn-produced junk
        esac
        run_applet_testcase "$applet" "$testcase" || {
            status=1
            total_failed=$((total_failed + 1))
        }
    done
    return $status
}

status=0
for applet in $applets; do
    # Any old-style tests for this applet?
    if [ -d "$tsdir/$applet" ]; then
        run_oldstyle_applet_tests "$applet" || status=1
    fi

    # Is this a new-style test?
    if [ -f "$applet.tests" ]; then
        if [ ! -e "$LINKSDIR/$applet" ]; then
            # (avoiding bash'ism "${applet:0:4}")
            if ! echo "$applet" | grep "^all_" >/dev/null; then
                echo "SKIPPED: $applet (not built)"
                continue
            fi
        fi
#		echo "Running test $tsdir/$applet.tests"
        PATH="$LINKSDIR:$tsdir:$bindir:$PATH" "$tsdir/$applet.tests"
        rc=$?
        total_failed=$((total_failed + rc))
        test $rc -ne 0 && status=1
    fi
done

# Clean up after ourselves.
rm -rf "$bindir"
rm -rf "$LINKSDIR"

if [ $status -ne 0 ] && [ x"$VERBOSE" = x ]; then
    echo "$total_failed failure(s) detected; running with -v (verbose) will give more info"
fi
exit $status
